<template>
  <div class="log-panel">
    <div class="log-container" ref="logContainer" @mousewheel="onScroll">
      <p
        :class="{
          log: true,
          info: logRow.type == 'stdout',
          error: logRow.type == 'stderr',
        }"
        v-for="(logRow, i) in visibleLogs"
        :key="i"
      >
        {{ logRow.content }}
      </p>
    </div>
    <el-slider
      v-model="lastLineNumberInverted"
      :min="1"
      :max="logs.length - 1 > 1 ? logs.length - 1 : 2"
      vertical
      height="90%"
      class="slider"
      :show-tooltip="false"
    />
  </div>
</template>

<script lang="ts" setup>
import { addOnMessageHandler } from "@/api/ws";
import { Plus, Document } from "@element-plus/icons-vue";
import {
  computed,
  reactive,
  ref,
  defineProps,
  defineExpose,
  PropType,
  onMounted,
  defineComponent,
} from "vue";
import { LogRow } from "../flowchart/models";

const search = ref("");
const show = ref(false);
const selectedPortID = ref("");
const routePortName = ref("");
const requireLogView = ref(false);
const logs: LogRow[] = reactive([]);

const lastLineNumberInverted = ref(0);
const logContainer = ref();
const LINES = 15;
const onDialogClose = (): void => {
  show.value = false;
};

const onDialogShow = (): void => {
  requireLogView.value = false;
  show.value = true;
};

const visibleLogs = computed(() => {
  const lastLineNumber = logs.length + LINES - lastLineNumberInverted.value;
  if (lastLineNumber < LINES) {
    return logs.slice(0, lastLineNumber);
  } else if (lastLineNumber - LINES > 0 && lastLineNumber < logs.length) {
    return logs.slice(lastLineNumber - LINES, lastLineNumber);
  } else {
    return logs.slice(
      logs.length - (LINES + logs.length - lastLineNumber),
      logs.length
    );
  }
});

onMounted(() => {
  addOnMessageHandler("subprocess-output", (s: LogRow) => {
    if (s.type == "stderr") {
      requireLogView.value = true;
    }
    logs.push(s);

    lastLineNumberInverted.value = LINES;
  });
});

const onScroll = (evt: WheelEvent) => {
  const newValue = lastLineNumberInverted.value - evt.deltaY;
  if (newValue > 1 && newValue <= logs.length - 1) {
    lastLineNumberInverted.value = newValue;
  }
  evt.preventDefault();
};

const clearLog = () => {
  logs.splice(0, logs.length);
  logs.push({
    type: "stdout",
    content: `Simulation started at:${new Date().toString()}`,
  });
};

defineExpose({ clearLog });
</script>

<style scoped>
.log {
  margin-top: 5px;
  margin-bottom: 5px;
  font-size: 0.9em;
}

:deep(.el-badge) {
  z-index: 500;
}

.info {
  color: black;
}

.error {
  color: red;
}
.log-panel {
  display: flex;
  padding-top: 8px;
}

.log-container {
  height: 100%;
  flex-grow: 1;
  /* max-width: 95%;
  min-width: 95%; */
  border: 1px solid var(--el-border-color);
  border-radius: var(--el-border-radius-small);
  overflow-x: scroll;
}

.slider {
  --slider-width: 10px;
}

.slider :deep(.el-slider__bar) {
  background-color: var(--el-slider-runway-bg-color);
}
.slider :deep(.el-slider__runway) {
  width: var(--slider-width);
}

.slider :deep(.el-slider__button) {
  border-radius: 4px;
  margin-left: 3px;
  width: var(--slider-width);
}
/* .log-container p {
  white-space: nowrap;
} */
</style>
